from keras.datasets import mnist
from tensorflow.compat.v1.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.compat.v1.keras.models import Sequential
from tensorflow.compat.v1.keras.utils import to_categorical
from tensorflow.compat.v1.keras.optimizers import RMSprop
import matplotlib.pyplot as plt

# 准备数据
(x_train, y_train), (x_test, y_test) = mnist.load_data()
print("数据集为:")
print(mnist.load_data())
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1).astype('float32') / 256
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1).astype('float32') / 256
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

# 构建神经网络模型
model = Sequential()
model.add(Conv2D(filters=16, kernel_size=(5, 5), padding='same', input_shape=(28, 28, 1), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(filters=36, kernel_size=(5, 5), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))

# train_history = model.fit(x=x_train, y=y_train: 这行代码表示使用model.fit()方法来训练模型。x参数表示输入数据（即训练数据），y参数表示输出数据（即训练数据的标签）。
# validation_split=0.2: 这行代码表示将输入数据划分为训练集和验证集，其中验证集占20%的数据量。这个参数用于在训练过程中监控模型的性能，以防止过拟合。
# epochs=15: 这行代码表示训练模型15个周期（epochs）。每个周期内，模型会遍历整个训练数据集。
# batch_size=300: 这行代码表示每个周期内，模型会使用300个数据样本进行训练。batch_size参数用于控制训练的效率，但会增加训练时间。
# verbose=2: 这行代码表示训练过程中的详细程度。verbose=0表示不输出任何信息，verbose=1表示输出进度条，verbose=2表示输出每个周期的损失函数值和准确率。



# 训练和评估神经网络模型
model.compile(loss='categorical_crossentropy', optimizer=RMSprop(lr=0.001), metrics=['accuracy'])
train_history = model.fit(x=x_train,
                          y=y_train,
                          validation_split=0.2,
                          epochs=15,
                          batch_size=300,
                          verbose=2)

# 获取训练过程中的损失函数值和准确率
loss = train_history.history['loss']
val_loss = train_history.history['val_loss']
acc = train_history.history['accuracy']
val_acc = train_history.history['val_accuracy']

# 绘制损失函数值折线图
epochs_range = range(1, len(loss) + 1)
plt.figure(figsize=(8, 6))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')

# 绘制准确率折线图
plt.subplot(1, 2, 2)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.show()


scores_test = model.evaluate(x_test, y_test, batch_size=512)
scores_train = model.evaluate(x_train, y_train, batch_size=512)
print("测试函数准确率为:", scores_test[1])
print("训练函数准确率为:", scores_train[1])
